package com.kun.video.thread;

import cn.hutool.core.util.StrUtil;
import com.kun.video.context.DestroyingBean;
import com.kun.video.exception.Assert;
import com.kun.video.util.ComUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.concurrent.*;
import java.util.function.Supplier;

/**
 * 抽象线程池基类，提供线程池的通用操作和生命周期管理
 * 子类需实现 {@link #createPool()} 方法以创建具体的线程池实例
 *
 * @author gzc
 * @since 2025/2/7
 **/
public abstract class AbstractThreadPool implements DestroyingBean {
    private static final Logger log = LoggerFactory.getLogger(AbstractThreadPool.class);

    /**
     * 内部线程池实例，子类通过 {@link #createPool()} 初始化
     */
    protected final ThreadPoolExecutor pool;

    /**
     * 构造方法，直接注入外部线程池实例
     *
     * @param pool 外部线程池实例（需非空）
     */
    protected AbstractThreadPool(ThreadPoolExecutor pool) {
        this.pool = Assert.notNull(pool, "线程池为空");
    }

    /**
     * 无参构造方法，通过 {@link #createPool()} 创建线程池实例
     */
    protected AbstractThreadPool() {
        this.pool = Assert.notNull(createPool(), "线程池创建失败: createPool()返回null");
    }

    //------------------------------- 任务提交方法 -------------------------------

    /**
     * 提交 Callable 任务，返回 Future 对象
     *
     * @param task 待执行的任务（需非空）
     * @return 关联任务结果的 Future
     */
    public <T> Future<T> submit(Callable<T> task) {
        FutureTask<T> futureTask = new FutureTask<>(task);
        execute(futureTask);
        return futureTask;
    }

    /**
     * 提交 Runnable 任务，返回 Future 对象
     *
     * @param task 待执行的任务（需非空）
     * @return 关联任务结果的 Future
     */
    public Future<?> submit(Runnable task) {
        return pool.submit(task);
    }

    /**
     * 在 UI 线程中执行任务（通过 {@link ComUtil#uiThreadRun(Runnable)}）
     *
     * @param task 待执行的 UI 任务（需非空）
     * @return 关联任务结果的 Future
     */
    public Future<?> submitUI(Runnable task) {
        return submit(() -> ComUtil.uiThreadRun(task));
    }

    /**
     * 直接执行 Runnable 任务
     *
     * @param task 待执行的任务（需非空）
     */
    public void execute(Runnable task) {
        pool.execute(task);
    }

    /**
     * 在 UI 线程中执行任务
     *
     * @param task 待执行的 UI 任务（需非空）
     */
    public void executeUI(Runnable task) {
        execute(() -> ComUtil.uiThreadRun(task));
    }

    //------------------------------- CompletableFuture 支持 -------------------------------

    /**
     * 异步执行 Runnable 任务，返回 CompletableFuture
     *
     * @param runnable 待执行的任务（需非空）
     * @return CompletableFuture 对象
     */
    public CompletableFuture<Void> runAsync(Runnable runnable) {
        return CompletableFuture.runAsync(runnable, pool);
    }

    /**
     * 在 UI 线程中异步执行任务
     *
     * @param runnable 待执行的 UI 任务（需非空）
     * @return CompletableFuture 对象
     */
    public CompletableFuture<Void> runAsyncUI(Runnable runnable) {
        return runAsync(() -> ComUtil.uiThreadRun(runnable));
    }

    /**
     * 将 Callable 任务包装为 CompletableFuture
     *
     * @param callable 待执行的任务（需非空）
     * @return CompletableFuture 对象
     */
    public <T> CompletableFuture<T> supplyAsyncCallable(Callable<T> callable) {
        return supplyAsync(() -> {
            try {
                return callable.call();
            } catch (Exception e) {
                // 统一包装异常
                throw new CompletionException(e);
            }
        });
    }

    /**
     * 异步执行 Supplier 任务，返回 CompletableFuture
     *
     * @param supplier 待执行的任务（需非空）
     * @return CompletableFuture 对象
     */
    public <T> CompletableFuture<T> supplyAsync(Supplier<T> supplier) {
        return CompletableFuture.supplyAsync(supplier, pool);
    }

    /**
     * 在 UI 线程中执行 Supplier 任务（注意：会阻塞当前线程直到完成）
     *
     * @param supplier 待执行的 UI 任务（需非空）
     * @return CompletableFuture 对象
     * @apiNote 此方法会在当前线程阻塞，避免在 UI 线程中调用
     */
    public <T> CompletableFuture<T> supplyAsyncUI(Supplier<T> supplier) {
        return supplyAsync(() -> {
            CompletableFuture<T> future = new CompletableFuture<>();
            ComUtil.uiThreadRun(() -> {
                try {
                    future.complete(supplier.get());
                } catch (Exception e) {
                    future.completeExceptionally(e);
                }
            });
            // 阻塞当前线程直到 UI 线程完成
            return future.join();
        });
    }

    //------------------------------- 其他方法 -------------------------------

    /**
     * 获取内部线程池实例
     *
     * @return 当前线程池对象
     */
    public ThreadPoolExecutor getPool() {
        return this.pool;
    }

    /**
     * 子类必须实现的抽象方法，用于创建线程池实例
     *
     * @return 非空的 ThreadPoolExecutor 实例
     */
    protected abstract ThreadPoolExecutor createPool();

    //------------------------------- 生命周期管理 -------------------------------

    /**
     * 打印线程池状态信息
     *
     * @return 包含线程池状态、线程数、任务数等信息的字符串
     */
    @Override
    public String toString() {
        String state = pool.isTerminated() ? "已终止" :
                pool.isShutdown() ? "关闭中" : "运行中";
        String queueType = pool.getQueue().getClass().getSimpleName();
        String param = "状态={}, 核心线程数={}, 最大线程数={}, 活跃线程数={}, 总任务数={}, 完成数={}, 队列大小={}, 队列类型={}";
        return StrUtil.format(param, state,
                pool.getCorePoolSize(), pool.getMaximumPoolSize(),
                pool.getActiveCount(), pool.getTaskCount(),
                pool.getCompletedTaskCount(), pool.getQueue().size(), queueType);
    }

    /**
     * 销毁线程池，关闭所有任务
     * 1. 停止接收新任务
     * 2. 等待现有任务完成（最多10秒）
     * 3. 强制终止未完成任务（如超时）
     */
    @Override
    public void destroy() {
        // 1. 停止接受新任务
        pool.shutdown();
        try {
            // 2. 等待现有任务完成
            if (!pool.awaitTermination(10, TimeUnit.SECONDS)) {
                log.warn("线程池未及时关闭，剩余任务数: {}", pool.getQueue().size());
                // 3. 强制取消未执行任务
                List<Runnable> droppedTasks = pool.shutdownNow();
                log.warn("强制关闭，丢弃任务数: {}", droppedTasks.size());
                // 4. 调用扩展点供子类处理
                onTasksDropped(droppedTasks);
            }
        } catch (InterruptedException e) {
            log.warn("线程池关闭被中断", e);
            pool.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }

    /**
     * 当有任务被丢弃时的回调方法（子类可重写）
     *
     * @param droppedTasks 被丢弃的任务列表
     */
    protected void onTasksDropped(List<Runnable> droppedTasks) {
        // 默认空实现，子类可按需处理
    }
}